/**
 * file :	db_interface.cpp
 * author :	bushaofeng
 * created :	2013-01-29 15:15
 * func : 
 */

#include <time.h>
#include <set>
#include "db_interface.h"

/**
 * 添加一个user
 */
state_t DBInterface::addUser(BSONObj user){
    cout<<"addUser"<<user.jsonString()<<endl;
    m_db.insert(m_users, user);
    if(m_db.getLastError()!=""){
        std::cout<<"Add User Error:"<<m_db.getLastError()<<std::endl;
        return BS_NOTFOUND;
    }
    return BS_SUCCESS;
}

state_t DBInterface::login(string user, string passwd){
    BSONObj obj = BSON("user"<<user<<"passwd"<<passwd);
    BSONObj rst = m_db.findOne(m_users, obj);
    if(m_db.getLastError()!=""){
        std::cout<<"Login Error:"<<m_db.getLastError()<<std::endl;
        return BS_INVALID;
    }
    else if(rst.nFields()==0){
        return BS_NOTFOUND;
    }
    return BS_SUCCESS;
}

/**
 * 更新一个user， 登录亦可用
 */
state_t DBInterface::updUser(string user, BSONObj obj){
    BSONObjBuilder      builder;
    set<string>         fields;

    obj.getFieldNames(fields);
    for(set<string>::iterator iter=fields.begin();
            iter!=fields.end(); iter++){
        builder.append("$set", BSON(*iter<<obj.getStringField(iter->c_str())));
    }

    //cout<<"updUser:"<<builder.obj().jsonString()<<endl;
    m_db.update(m_users, BSON("user"<<user), builder.obj());

    if(m_db.getLastError()!=""){
        std::cout<<"Upd User Error:"<<m_db.getLastError()<<std::endl;
        return BS_INVALID;
    }
    return BS_SUCCESS;
}

BSONObj DBInterface::getUser(string user){
    return m_db.query(m_users, BSON("user"<<user));
}
/**
 * 添加user的关注
 */
state_t DBInterface::addFollow(string user, string follow){
    m_db.update(m_follows, BSON("user"<<user), BSON("$addToSet"<<BSON("fol"<<follow)), true);
    if(m_db.getLastError()!=""){
        std::cout<<"Add Follow Error:"<<m_db.getLastError()<<std::endl;
        return BS_INVALID;
    }
    return BS_SUCCESS;
}
/**
 * 获取user的关注列表
 */
BSONObj DBInterface::getFollows(string user, int start, int num){
    if(num==0){
        return m_db.findOne(m_follows, BSON("user"<<user))["fol"].Obj();
    }else{
        BSONObj obj = BSON("fol"<<1<<"_id"<<0<<"fol"<<BSON("$slice"<<BSON_ARRAY(start<<num)));
        return m_db.findOne(m_follows, BSON("user"<<user), &obj)["fol"].Obj();
    }
}
/**
 * 删除user的关注
 */
state_t DBInterface::delFollow(string user, string follow){
    m_db.update(m_follows, BSON("user"<<user), BSON("$pull"<<BSON("fol"<<follow)));
    if(m_db.getLastError()!=""){
        std::cout<<"Del Follow  Error:"<<m_db.getLastError()<<std::endl;
        return BS_INVALID;
    }
    return BS_SUCCESS;
}
/**
 * 添加user的粉丝（一个人的好友关系为2个表，我的关注表，我的粉丝表即关注我的人）
 */
state_t DBInterface::addFan(string user, string fan){
    m_db.update(m_fans, BSON("user"<<user), BSON("$addToSet"<<BSON("fan"<<fan)), true);
    if(m_db.getLastError()!=""){
        std::cout<<"Add Fan Error:"<<m_db.getLastError()<<std::endl;
        return BS_INVALID;
    }
    return BS_SUCCESS;
}
/**
 * 获取关注user的列表
 */
BSONObj DBInterface::getFans(string user, int start, int num){
    if(num==0){
        return m_db.findOne(m_follows, BSON("user"<<user))["fan"].Obj();
    }else{
        BSONObj obj = BSON("fan"<<1<<"_id"<<0<<"fan"<<BSON("$slice"<<BSON_ARRAY(start<<num)));
        return m_db.findOne(m_follows, BSON("user"<<user), &obj)["fan"].Obj();
    }
}

long long DBInterface::addTopic(BSONObj topic){
    BSONObj             robj;
    BSONObjBuilder      builder;
    long long           id = 0;

    builder.append("findAndModify", m_counter);
    builder.append("query", BSON("_id"<<m_topics));
    builder.append("update", BSON("$inc"<<BSON("counter"<<(long long)1)));
    builder.append("new", true);
    builder.append("upsert", true);
    BSONObj obj = builder.obj();
    cout<<"addTopic:"<<obj.jsonString()<<endl;
    m_db.runCommand(m_dbname, obj, robj);
    if(m_db.getLastError()!=""){
        std::cout<<"Add Topic Error:"<<m_db.getLastError()<<std::endl;
        return false;
    }

    if(robj.getField("value").isNull()){
        return -1;
        /*
        m_db.insert(m_counter, BSON("_id"<<m_topics<<"counter"<<1));
        return addTopic(topic);
        */
    }
    if(robj["value"]["counter"].type()==NumberInt){
        id = robj["value"]["counter"].Int();
    }
    else{
        id = robj["value"]["counter"].Long();
    }

    BSONObjBuilder tbuilder;
    
    tbuilder.append("_id", id);
    tbuilder.append("_tm", (unsigned int)time(0));
    for( BSONObj::iterator i = topic.begin(); i.more(); ){
        BSONElement e = i.next();
        tbuilder.append(e);
    }
    BSONObj t=tbuilder.obj();
    std::cout<<"insert: "<<t.jsonString()<<std::endl;
    m_db.insert(m_topics, t);

    //添加到fans的inbox
    // 另外一个选择是发送到dbserver，异步执行，此处直接返回
    // dbserver处理对时间要求低的请求
    try{
        BSONObj fans = getFans(topic.getField("user").String());
        BSONObjIterator iter(fans);
        BSONForEach(iter, fans){
            m_db.update(m_inbox, BSON("user"<<iter.toString()), BSON("$push"<<BSON("in"<< id)), true);
        }
    }catch(DBException& e){
        cout<<"Get Fans Error:"<<e.what()<<endl;
    }

    return id;
}

/**
 * 获取user的发表
 */
BSONObj DBInterface::getTopics(string user, int start, int num){
    return m_db.query(m_topics, BSON("user"<<user));
}
/**
 * 获取一个发表
 */
BSONObj DBInterface::getTopic(long long topic){
    return m_db.findOne(m_topics, BSON("_id"<<topic));
}
/**
 * 获取评论
 */
BSONObj DBInterface::getPosts(string topic){
    BSONObjBuilder      builder;
    BSONObj             obj;
    
    return obj;
}
/**
 * 获取user的位置列表
 */
BSONObj DBInterface::getLocations(string user, int start ,int num){
    BSONObjBuilder      builder;
    BSONObj             obj;
    
    if(num==0){
        return m_db.findOne(m_follows, BSON("user"<<user))["fol"].Obj();
    }else{
        BSONObj obj = BSON("fol"<<1<<"_id"<<0<<"fol"<<BSON("$slice"<<BSON_ARRAY(start<<num)));
        return m_db.findOne(m_follows, BSON("user"<<user), &obj)["fol"].Obj();
    }
    return obj;
}
/**
 * 获取附近user
 */
BSONObj DBInterface::getNearUsers(double x, double y, int start, int num){
    //BSONObj     obj = BSON("loc"<<1<<"_id"<<0);
    return m_db.query(m_users, BSON("gps"<<BSON("$near"<<BSON_ARRAY(x<<y))));
                
}
/**
 * 获取附近发表
 */
BSONObj DBInterface::getNearTopics(double x, double y, int start, int num){
    return m_db.query(m_topics, BSON("gps"<<BSON("$near"<<BSON_ARRAY(x<<y))));
}
